#include <QPainter>
#include <QtGui>
#include <QTextCodec>
#include <cstdio>
#include <cassert>
//#include <QGraphicsRectItem>

#include "boardscene.h"
#include "stones.h"
#include "moyos.h"
#include "grid.h"
#include "go.h"
#include "step.h"
#include "record.h"
#include "index.h"
#include "io_sgf/io_sgf.h"
#include "settings.h"

BoardScene::BoardScene()
{
    info_index = 0;
    htzs = 0; btzs = 0;
    ifShowIndex = false;
    createColor();
    setTextCode();
    createInfoBlock();

    /* square is always there as long as a game is begin
     * it tells users where is the last move
     */
    square = new QGraphicsRectItem(0,0,18,18);
    square->setPen(QPen(Qt::gray, 1, Qt::SolidLine, Qt::SquareCap));
    this->addItem(square);
    square->setZValue(2);
    //square->setPos(((30*(x-1))+20),((30*(y-1))+20));
    square->hide();

    pcore = new Go(); //create a core obj
    pjudgment = new Judgment(); //create a Judgment obj
}

/** FIXME: when GUI terminated, this destructor wont be invoked??? **/
BoardScene::~BoardScene()
{
    //necessary to clear moyosOperator case program terminated when running judgment
    map<coordinate, Moyos*>::iterator iter2;
    if(!moyosOperator.empty())
    {
        for(iter2=moyosOperator.begin(); iter2!=moyosOperator.end(); iter2++)
        {
            delete iter2->second;
        }
    }

    map<coordinate, Stones*>::iterator iter;
    for(iter=stonesOperator.begin(); iter!=stonesOperator.end(); iter++)
    {
        deleteStone((iter->first).first, (iter->first).second); //include delete index
    }
    delete pcore;
    delete pjudgment;
}

void BoardScene::setTextCode()
{
    /* set GBK Unicode encoding */
    //QTextCodec *textc = QTextCodec::codecForName("GB2312");
    QTextCodec *textc = QTextCodec::codecForName("UTF-8");
    //QTextCodec *textc = QTextCodec::codecForLocale(); //better
    QTextCodec::setCodecForCStrings(textc);
    QTextCodec::setCodecForTr(textc);
    QTextCodec::setCodecForLocale(textc);
}

void BoardScene::goCore(int x, int y)
{
    pcore->doit(x,y); //the main funcion in Class Go, begin operating
}

void BoardScene::drawBackground(QPainter *painter, const QRectF &rect)
{
    /* draw GameBoard */
    painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::SquareCap));
    painter->setBrush(QBrush(*boardColor, Qt::SolidPattern));
    painter->drawRect(0, 0, 600, 600);
    for(int i = 30; i<600; i = i+30)
    {
        painter->drawLine(30, i, 570, i);
        painter->drawLine(i,30, i, 570);
    }
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap));
    painter->drawPoint(120,120); painter->drawPoint(300,120); painter->drawPoint(480,120);
    painter->drawPoint(120,300); painter->drawPoint(300,300); painter->drawPoint(480,300);
    painter->drawPoint(120,480); painter->drawPoint(300,480); painter->drawPoint(480,480);

    /* draw InfoBlock */
    painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::SquareCap));
    painter->setBrush(QBrush(*infoBlockColor, Qt::SolidPattern));
    painter->drawRect(600, 0, 200, 600);
    painter->drawLine(600, 200, 800,200);
    painter->drawLine(600, 400, 800, 400);
}

void BoardScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if(!(getPosition(event->scenePos())))
        {
            return;
        }
        else
        {
            /** 如果对这里有相关修改, 记得考虑在读取棋局的函数inputCore()中是否需要相应修改 **/

            goCore(xpos,ypos); //operating Data from CoreCode

            if(!((pcore->drawSerie).empty()))
            {
                //if we do make a certain move, then we emit some signals to operating GUI
                if(!(pcore->game_status))
                {
                    emit changeButtonToFalse();
                }
                else
                {
                    emit windowIsModified();

                    if(pcore->block_index == 2)
                    {
                        emit openReview();
                        emit disableGameSettings();
                    }
                }

                int x,y;
                int color = (-1)*(pcore->whos_turn); //atm the value of whos_turn doesnt represtent the current status
                                                     //so it has to be multiplied by -1 once more
                vector<coordinate>::iterator ibegin = (pcore->drawSerie).begin();
                vector<coordinate>::iterator iend = (pcore->drawSerie).end();

                //draw the current stone
                x = ibegin->first;
                y = ibegin->second;
                createStone(color,x,y);
                if(pcore->game_status) //不处于复盘状态时候的index
                {
                    createIndex(color,x,y,(pcore->block_index)-1);

                    //change items in infoBlock
                    changeIndexLableString(++info_index);
                    changeSquare(x,y);
                    changeYesImage(pcore->whos_turn);
                    //change finish
                }
                else //复盘状态下的index
                {
                    if(pcore->latestStep != 0) //保证棋盘上还有子的情况下进行的试下
                    {
                        unsigned delta = pcore->latestStep->getIndex(); //delta >= 1
                        unsigned int i = pcore->block_index - delta - 1;

                        createIndex(color,x,y,i);
                    }
                    else //在棋盘为空即 pcore->latestStep ==0 的情况下进行的着子
                    {
                        createIndex(color,x,y,pcore->block_index-1); //delta = 0
                    }
                }
                ibegin++;

                //take off other stones if have to do so
                for(ibegin; ibegin!=iend; ibegin++) //ibegin statement throw out a warning ignore it, it should be fine
                {
                    x = ibegin->first;
                    y = ibegin->second;
                    deleteStone(x,y);

                    //change htzs&btzs in infoBlock
                    if(pcore->game_status)
                    {
                        if( color == BLACK )
                        {
                            htzs++;
                        }
                        else btzs++;
                    }
                }
                //update change
                if(pcore->game_status)
                {
                    if(color == BLACK)
                    {
                        changeIndexTZS(BLACK, htzs);
                    }
                    else changeIndexTZS(WHITE, btzs);
                } //change finish

                //drawSerie will be initialized in Go class it self not here
                pcore->drawSerie.erase((pcore->drawSerie).begin(), (pcore->drawSerie).end()); //delete all elements in the drawSerie Vector
            }
            else return;
        }
    }
}

void BoardScene::changeYesImage(int bw)
{
    if(pcore->game_status)
    {
        if(bw == BLACK)
        {
            infoLSX->setPos(730,220);
        }
        if(bw == WHITE)
        {
            infoLSX->setPos(730,420);
        }
    }
}

void BoardScene::changeSquare(int x, int y)
{
    if(pcore->game_status)
    {
        //如果不是PASS则更新这个图标的位置, 否则不变
        if(x!=ERROR && y!=ERROR)
        {
            square->setPos(((30*(x-1))+21.00),((30*(y-1))+20.9));
            square->show();
        }
    }
}

void BoardScene::changeIndexLableString(unsigned int i)
{
    if(infoIndexLable != 0)
    {
        delete infoIndexLable;
    }

    if(pcore->game_status) //normal mode
    {
        infoIndexLable = new Index(-1, i);
        this->addItem(infoIndexLable);
        infoIndexLable->setPos(720,42.5);
        infoNormalGroup->addToGroup(infoIndexLable);

        update();
    }
    else //review mode
    {

    }
}

void BoardScene::changeIndexTZS(int bw, unsigned int num)
{
    if(pcore->game_status)
    {
        if(bw == BLACK)
        {
            if(infoIndexHTZS != 0)
            {
                delete infoIndexHTZS;
            }
            infoIndexHTZS = new Index(-1, num);
            this->addItem(infoIndexHTZS);
            infoIndexHTZS->setPos(730, 329.5);
            infoNormalGroup->addToGroup(infoIndexHTZS);

            update();
        }
        if(bw == WHITE)
        {
            if(infoIndexBTZS != 0)
            {
                delete infoIndexBTZS;
            }
            infoIndexBTZS = new Index(-1, num);
            this->addItem(infoIndexBTZS);
            infoIndexBTZS->setPos(730, 529.5);
            infoNormalGroup->addToGroup(infoIndexBTZS);

            update();
        }

    }
}

void BoardScene::createInfoBlock()
{
    //create all Items in Normal Mode for InfoBlock

    char *dangQianShouShu = "当前手数 :";
    infoDQSS = new QGraphicsSimpleTextItem(tr(dangQianShouShu));
    this->addItem(infoDQSS);
    infoDQSS->setPos(660,50);
    infoIndexLable = new Index(-1, info_index);
    this->addItem(infoIndexLable);
    infoIndexLable->setPos(720,42.5);

    black = new Stones(BLACK); this->addItem(black);
    white = new Stones(WHITE); this->addItem(white);
    black->setPos(630,230); white->setPos(630,430);
    char *hei = "黑"; char *bai = "白";
    infoH = new QGraphicsSimpleTextItem(tr(hei));
    infoB = new QGraphicsSimpleTextItem(tr(bai));
    this->addItem(infoH); this->addItem(infoB);
    infoH->setPos(680,237); infoB->setPos(680,437);

    char *yongShi = "用时 :";
    char *tiZiShu = "提子数 :";
    infoHYS = new QGraphicsSimpleTextItem(tr(yongShi));
    infoBYS = new QGraphicsSimpleTextItem(tr(yongShi));
    infoHTZS = new QGraphicsSimpleTextItem(tr(tiZiShu));
    infoBTZS = new QGraphicsSimpleTextItem(tr(tiZiShu));
    this->addItem(infoHYS); this->addItem(infoHTZS);
    this->addItem(infoBYS); this->addItem(infoBTZS);
    infoHYS->setPos(680,287); infoHTZS->setPos(680,337);
    infoBYS->setPos(680,487); infoBTZS->setPos(680,537);

    infoIndexHTZS = new Index(-1, htzs);
    infoIndexBTZS = new Index(-1, btzs);
    this->addItem(infoIndexHTZS);
    this->addItem(infoIndexBTZS);
    infoIndexHTZS->setPos(730, 329.5);
    infoIndexBTZS->setPos(730, 529.5);

    QPixmap *yesImage = new QPixmap(":/images/yes.png");
    infoLSX = new QGraphicsPixmapItem(*yesImage);
    this->addItem(infoLSX);
    infoLSX->setPos(730,220);
    infoLSX->scale(0.3,0.3);

    //make ItemGroup for Normal Mode *** infoIndexLable需要进行额外的操作, 也许是因为会进行删除和重新创建工作
    infoNormalGroup = new QGraphicsItemGroup();
    infoNormalGroup->addToGroup(infoIndexLable); infoNormalGroup->addToGroup(infoDQSS);
    infoNormalGroup->addToGroup(infoH); infoNormalGroup->addToGroup(infoB);
    infoNormalGroup->addToGroup(infoHYS); infoNormalGroup->addToGroup(infoBYS);
    infoNormalGroup->addToGroup(infoHTZS); infoNormalGroup->addToGroup(infoBTZS);
    infoNormalGroup->addToGroup(infoLSX); infoNormalGroup->addToGroup(black);
    infoNormalGroup->addToGroup(white); infoNormalGroup->addToGroup(infoIndexHTZS);
    infoNormalGroup->addToGroup(infoIndexBTZS);
    this->addItem(infoNormalGroup);
}

void BoardScene::createColor()
{
    boardColor = new QColor(205,149,12,200); //color for goboard
    infoBlockColor = new QColor(205,149,12,200); //color for infoblock
}

void BoardScene::createStone(int color, int x, int y)
{
    coordinate temp; //typedef in go.h
    temp.first = x; temp.second = y;

    Stones *stone = new Stones(color);
    stone->setPos(((30*(x-1))+16),((30*(y-1))+16));
    this->addItem(stone);
    stonesOperator.insert(map<coordinate,Stones*>::value_type(temp,stone));

    /*if(pcore->game_status)
    {
        Index *index = new Index(color, (pcore->block_index)-1);
        index->setPos(((30*(x-1))+16),((30*(y-1))+16));
        this->addItem(index);
        indexOperator.insert(map<coordinate,Index*>::value_type(temp,index));
        if(!ifShowIndex)
        {
            index->hide();
        }
    }*/

    update();
}

void BoardScene::deleteStone(int x, int y)
{
    coordinate temp;
    temp.first = x; temp.second = y;
    map<coordinate, Stones*>::iterator iter;

    iter = stonesOperator.find(temp);
    delete iter->second;

    stonesOperator.erase(iter);

    if(pcore->game_status)
    {
        deleteIndex(x,y);
    }
    else
    {
        if(!pcore->ifCoverLatest())
        {
            deleteIndex(x,y);
        }
    }

    update();
}

void BoardScene::createMoyos(int color, int x, int y)
{
    coordinate temp; //typedef in go.h
    temp.first = x; temp.second = y;

    Moyos *moyo = new Moyos(color);
    moyo->setPos(((30*(x-1))+22.5),((30*(y-1))+22.5));
    this->addItem(moyo);
    moyosOperator.insert(map<coordinate,Moyos*>::value_type(temp,moyo));

    update();
}

void BoardScene::deleteMoyos(int x, int y)
{
    coordinate temp;
    temp.first = x; temp.second = y;
    map<coordinate, Moyos*>::iterator iter;

    iter = moyosOperator.find(temp);
    delete iter->second;

    update();
}

void BoardScene::createAllMoyos()
{

    for(int x=1; x<DIMENSION-1; x++)
    {
        for(int y=1; y<DIMENSION-1; y++)
        {
            if(pcore->board[x][y] != pjudgment->board[x][y])
            {
                assert(pjudgment->board[x][y] != VOID);

                createMoyos(pjudgment->board[x][y], x, y);
            }
        }
    }
}

void BoardScene::deleteAllMoyos()
{
    map<coordinate, Moyos*>::iterator iter;

    for(iter=moyosOperator.begin(); iter!=moyosOperator.end(); iter++)
    {
        delete iter->second;
    }

    moyosOperator.clear();
}

void BoardScene::createIndex(int color, int x, int y, unsigned int i)
{
    if(pcore->game_status)  //正常状态下
    {
        coordinate temp; //typedef in go.h
        temp.first = x; temp.second = y;

        Index *index = new Index(color, i);
        index->setPos(((30*(x-1))+16),((30*(y-1))+16));
        this->addItem(index);
        indexOperator.insert(map<coordinate,Index*>::value_type(temp,index));
        if(!ifShowIndex)
        {
            index->hide();
        }

        update();
    }

    else //复盘状态下
    {
        coordinate temp; //typedef in go.h
        temp.first = x; temp.second = y;

        Index *index = new Index(color, i);
        index->setPos(((30*(x-1))+16),((30*(y-1))+16));
        this->addItem(index);
        reviewIndexOperator.insert(map<coordinate,Index*>::value_type(temp,index));

        update();
    }
}

void BoardScene::deleteIndex(int x, int y)
{
    if(pcore->game_status) //正常状态下
    {
        coordinate temp; //typedef in go.h
        temp.first = x; temp.second = y;

        map<coordinate, Index*>::iterator it;
        it = indexOperator.find(temp);
        if(it!=indexOperator.end())
        {
            delete it->second;
            indexOperator.erase(it);
        }

        update();
    }
    else //复盘状态下
    {
        coordinate temp; //typedef in go.h
        temp.first = x; temp.second = y;

        map<coordinate, Index*>::iterator it;
        it = reviewIndexOperator.find(temp);
        if(it!=reviewIndexOperator.end())
        {
            delete it->second;
            reviewIndexOperator.erase(it);
        }

        update();
    }
}

void BoardScene::refreshIndex()
{

if(pcore->game_status) //正常状态下
{
    /* delete all index obj and clear indexOperator */
    map<coordinate, Index*>::iterator iter;
    for(iter = indexOperator.begin(); iter!=indexOperator.end(); iter++)
    {
        delete iter->second;
    }
    //iter = 0;
    indexOperator.clear();

    /* recreate all index witch bind to exist stone through record Steps*/
    for(unsigned int i=1; i<(pcore->block_index); i++)
    {
        //如果这手棋的属性不是PASS则执行index的恢复工作
        if(!((pcore->record->getStep(i))->ifPass())){
        int x,y;
        int color;
        coordinate coo;
        map<coordinate, Stones*>::iterator it;


        x = (pcore->record->getStep(i))->getCoordinateX();
        y = (pcore->record->getStep(i))->getCoordinateY();
        coo.first = x; coo.second = y;
        color = (pcore->record->getStep(i))->getColor();

        it = stonesOperator.find(coo);
        if(it!=stonesOperator.end())
        {
            /* 由于遍历Steps会遇到被提吃的子, 并且同样位置后来被占据, 造成显示2个手数
               通过下面的判断将较早的一个删除 */
            map<coordinate, Index*>::iterator ite = indexOperator.find(coo);
            if(ite!=indexOperator.end())
            {
                deleteIndex(coo.first, coo.second);
            }

            createIndex(color, x, y, i);
        }
        }
    }

    update();
}

else //复盘状态下
{
    /* delete all index obj and clear reviewIndexOperator */
    map<coordinate, Index*>::iterator iter;
    for(iter = reviewIndexOperator.begin(); iter!=reviewIndexOperator.end(); iter++)
    {
        delete iter->second;
    }
    //iter = 0;
    reviewIndexOperator.clear();

    /* recreate all index witch bind to exist stone through recordBackup Steps*/
    unsigned int delta;
    if(pcore->latestStep == 0)
    {
        delta = 0;
    }
    else delta = pcore->latestStep->getIndex();
    for(unsigned int i=delta+1; i<(pcore->block_index); i++)
    {
        int x,y;
        int color;
        coordinate coo;
        map<coordinate, Stones*>::iterator it;

        //这里不需要考虑PASS属性的Step对象, 因为在复盘模式下禁止使用PASS功能
        x = (pcore->record->getStepBU(i))->getCoordinateX();
        y = (pcore->record->getStepBU(i))->getCoordinateY();
        coo.first = x; coo.second = y;
        color = (pcore->record->getStepBU(i))->getColor();

        it = stonesOperator.find(coo);
        if(it!=stonesOperator.end())
        {
            /* 由于遍历Steps会遇到被提吃的子, 并且同样位置后来被占据, 造成显示2个手数
               通过下面的判断将较早的一个删除 */
            map<coordinate, Index*>::iterator ite = reviewIndexOperator.find(coo);
            if(ite!=reviewIndexOperator.end())
            {
                deleteIndex(coo.first, coo.second);
            }

            createIndex(color, x, y, (i-delta));
        }
    }

    update();
}

}

void BoardScene::createGrid()
{
        grid = new Grid();
        grid->setPos(30,12);
        this->addItem(grid);

        update();
}

void BoardScene::deleteGrid()
{
        delete grid;
        update();
}

void BoardScene::showIndex()
{
    //ifShowIndex = true;

    map<coordinate, Index*>::iterator iter;
    for(iter=indexOperator.begin(); iter!=indexOperator.end(); iter++)
    {
        iter->second->setVisible(true);
    }

    update();
}

void BoardScene::hideIndex()
{
    //ifShowIndex = false;

    map<coordinate, Index*>::iterator iter;
    for(iter=indexOperator.begin(); iter!=indexOperator.end(); iter++)
    {
        iter->second->setVisible(false);
    }

    update();
}

void BoardScene::changeIfShowIndex(bool b)
{
    ifShowIndex = b;
}

bool BoardScene::getPosition(QPointF point)
{
    qreal x; qreal y;

    x = point.rx();
    y = point.ry();

    for(int i = 1; i<20; i++)
    {
        if( (x>(15+((i-1)*30))) && (x<(45+((i-1)*30))) )
        {
            xpos = i;
            for(int j = 1; j<20; j++)
            {
                if( (y>(15+((j-1)*30))) && (y<(45+((j-1)*30))) )
                {
                    ypos = j;
                    return true; //find the position on board
                }
            }
        }
    }
    return false; //outside board
}

/* SLOTS linking functions for UI interaction */
void BoardScene::startReview()
{
    pcore->game_status =  false; //enter Review(recordBackup) mode
    pcore->setIcl(true);
    pcore->record->copyToBackup();

    hideIndex();
    square->hide();
    infoNormalGroup->hide();
    //infoIndexLable->hide();

    emit disableShowIndex();
}

void BoardScene::backToFirst()
{
    if(pcore->block_index == 1)
    {
        //输出已经是最前面了
        return;
    }
    else
    {
        pcore->initZeroStep();
        pcore->coverLatestStep(0);

        redraw();
    }
}

void BoardScene::jumpBackward()
{
    if(pcore->block_index == 1)
    {
        //输出已经是最前面了
        return;
    }
    else
    {
        if(pcore->block_index <= 11)
        {
            pcore->initZeroStep();
            pcore->coverLatestStep(0);

            redraw();
        }
        else
        {
            int i = pcore->block_index;
            Step *recoverToStep = pcore->record->getStepBU(i-11);
            pcore->recoverStep(recoverToStep);
            pcore->coverLatestStep(recoverToStep);

            redraw();
        }
    }
}

void BoardScene::backward()
{
    if(!pcore->ifCoverLatest())
    {
        unsigned int i;
        if(pcore->latestStep == 0)
        {
            i = 1;
        }
        else i = (pcore->latestStep->getIndex())+1;
        if((pcore->block_index) <= i)
        {
            return;
        }
    }
    switch(pcore->block_index)
    {
        case 1:
            break;
        case 2: //这个情况下只有一颗子, 直接从stonesOperator中删除即可
        {
            //map<coordinate, Stones*>::iterator iter = stonesOperator.begin();
            //deleteStone((iter->first).first, (iter->first).second);
            pcore->initZeroStep();
            pcore->coverLatestStep(0);

            redraw();

            break;
        }
        default:
        {
            int i = pcore->block_index;
            Step *recoverToStep = pcore->record->getStepBU(i-2);
            pcore->recoverStep(recoverToStep);
            pcore->coverLatestStep(recoverToStep);

            redraw();

            break;
        }
    }
    refreshIndex();
}

void BoardScene::forward()
{
    if(pcore->record->getLastStepBU() != 0)
    {
        if( (pcore->block_index) == ((pcore->record->getLastStepBU())->getIndex())+1 )
        {
            // 输出警告已经是最后一手棋了, 不能再往后
            return;
        }
        else
        {
            int i = pcore->block_index;
            Step *recoverToStep = pcore->record->getStepBU(i);
            pcore->recoverStep(recoverToStep);
            pcore->coverLatestStep(recoverToStep);

            redraw();
            refreshIndex();
        }
    }
    else
    {
        //没有下一手的记录
        return;
    }
}

void BoardScene::jumpForward()
{
    if(pcore->record->getLastStepBU() != 0)
    {
        if( (pcore->block_index) == ((pcore->record->getLastStepBU())->getIndex())+1 )
        {
            // 输出警告已经是最后一手棋了, 不能再往后
            return;
        }
        else
        {
            int i = pcore->block_index;
            Step *recoverToStep = pcore->record->getStepBU(i+9);

            if(recoverToStep != 0)
            {
                pcore->recoverStep(recoverToStep);
                pcore->coverLatestStep(recoverToStep);

                redraw();
            }
            else
            {
                recoverToStep = pcore->record->getLastStepBU();
                pcore->recoverStep(recoverToStep);
                pcore->coverLatestStep(recoverToStep);

                redraw();
            }
        }
    }
    else
    {
        //没有下一手的记录
        return;
    }
}

void BoardScene::goToEnd()
{
    if(pcore->record->getLastStepBU() != 0)
    {
        if( (pcore->block_index) == ((pcore->record->getLastStepBU())->getIndex())+1 )
        {
            // 输出警告已经是最后一手棋了, 不能再往后
            return;
        }
        else
        {
            Step *recoverToStep = pcore->record->getLastStepBU();
            pcore->recoverStep(recoverToStep);
            pcore->coverLatestStep(recoverToStep);

            redraw();
        }
    }
    else
    {
        //没有下一手的记录
        return;
    }
}

void BoardScene::backToInit()
{
    pcore->record->clearBackup(); //clear recordBackup
    pcore->record->copyToBackup();
    pcore->setIcl(true);
    if(pcore->latestStep == 0)
    {
        pcore->initZeroStep();
        redraw();
    }
    else
    {
        pcore->recoverStep(pcore->latestStep);
        redraw();
    }
    refreshIndex();
}

void BoardScene::quitReview()
{
    backToInit();

    pcore->game_status = true; //back to normal mode

    pcore->latestStep = pcore->tempLatestStep;

    pcore->record->clearBackup(); //clear recordBackup

    if((pcore->record->getLastStep()) != 0)
    {
        pcore->recoverStep(pcore->record->getLastStep()); //recover data in pcore to the last step
    }
    else pcore->initZeroStep();

    //then recover stones and index on the board
    if(ifShowIndex)
    {
        showIndex();
    }
    else hideIndex();
    redraw();

    square->show();
    infoNormalGroup->show();
    //infoIndexLable->show();

    emit enableShowIndex();
}

void BoardScene::regret()
{
    if(pcore->game_status == true)
    {
        emit windowIsModified();

        //change htzs&btzs in infoBlock
        unsigned int num = 0;
        if(info_index > 1)
        {
            num = pcore->tempLatestStep->getNumOfDeadStones();
        }
        //finish , we get the value of num

        coordinate coo;
        coo = pcore->regret();

        if(coo.first != ERROR)
        {
            if(pcore->tempLatestStep == 0)
            {
                //pcore->initZeroStep(); 放入了Go::regret()中
                emit closeReview();

                square->hide();
            }
            else
            {
                //pcore->recoverStep(pcore->tempLatestStep); 放入了Go::regret()中

                if(!(pcore->tempLatestStep->ifPass())){
                changeSquare((pcore->tempLatestStep->getCoordinateX()),
                             (pcore->tempLatestStep->getCoordinateY()));
                }
                else
                {
                    square->hide();
                }
            }

            redraw();
            refreshIndex();
            changeIndexLableString(--info_index);
            changeYesImage(pcore->whos_turn);
            if(pcore->whos_turn == BLACK)
            {
                htzs = htzs - num;
                changeIndexTZS(BLACK, htzs);
            }
            else
            {
                btzs = btzs - num;
                changeIndexTZS(WHITE, btzs);
            }
        }
        else
        {
            return; //已经没有棋可以悔了
        }
    }
}

/* redraw() redraws all stones on board
 * but before that it is important to
 * recover all necessary data in core obj
 * this ensure core can do right things
 * recover funcion is named recoverStep()
 * which been written in functions.cpp
 */
void BoardScene::redraw()
{
    for(register int x = 1; x<DIMENSION-1; x++)
    {
        for(register int y = 1; y<DIMENSION-1; y++)
        {
            coordinate coo; coo.first = x; coo.second = y;
            map<coordinate, Stones*>::iterator iter;
            iter = stonesOperator.find(coo);
            if(iter == stonesOperator.end())
            {
                if((pcore->board[x][y])!=VOID)
                {
                    createStone((pcore->board[x][y]), x, y);
                }
            }
            else
            {
                int c = iter->second->getColor(); //getColor for current stone
                if(c != (pcore->board[x][y]))
                {
                    deleteStone(x, y);
                    if((pcore->board[x][y])!=VOID)
                    {
                        createStone((pcore->board[x][y]), x, y);
                    }
                }
            }
        }
    }
}

void BoardScene::startJudgment()
{
    coordinate coo;
    coo = pjudgment->moyoCalculateINFLUENCE(pcore->board);

    QString s1,s2,s3,s4,s5,s6,s_all;
    s1 = "黑棋一共 "; s3 = " 子, ";
    s4 = "白棋一共 "; s6 = " 子.";
    s2.setNum(coo.first);
    s5.setNum(coo.second);

    s_all = s1.append(s2).append(s3).append(s4).append(s5).append(s6);

    createAllMoyos();
    emit showJudgment(s_all);
}

void BoardScene::pass()
{
    emit windowIsModified();

    /* 内部数据的变化调用pcore中的pass()函数 */
    pcore->pass();

    /* 界面的变化在这里完成 */
    changeIndexLableString(++info_index);
    changeYesImage(pcore->whos_turn);
    square->hide();
}

void BoardScene::aiMove()
{
    //check if we created MoveGenerator or not
    if(!pcore->ifMoveGenCreated())
    {
        pcore->createMoveGenerator();
    }

    coordinate coo = pcore->moveGen_ABMinMax();

    //after get the coordinate we make a move and change GUI&core
    //from here is almost same with operating in mousePressEvent()
    goCore(coo.first,coo.second); //operating Data from CoreCode

    emit windowIsModified();

    if(pcore->block_index == 2)
        {
            emit openReview();
            emit disableGameSettings();
        }

    int x,y;
    int color = (-1)*(pcore->whos_turn); //atm the value of whos_turn doesnt represtent the current status
                                        //so it has to be multiplied by -1 once more
    vector<coordinate>::iterator ibegin = (pcore->drawSerie).begin();
    vector<coordinate>::iterator iend = (pcore->drawSerie).end();

    //draw the current stone
    x = ibegin->first;
    y = ibegin->second;
    createStone(color,x,y);
    createIndex(color,x,y,(pcore->block_index)-1);

    //change items in infoBlock
    changeIndexLableString(++info_index);
    changeSquare(x,y);
    changeYesImage(pcore->whos_turn);
    //change finish

    ibegin++;

    //take off other stones if have to do so
    for(ibegin; ibegin!=iend; ibegin++) //ibegin statement throw out a warning ignore it, it should be fine
    {
        x = ibegin->first;
        y = ibegin->second;
        deleteStone(x,y);

        //change htzs&btzs in infoBlock
        if( color == BLACK )
        {
            htzs++;
        }
        else btzs++;
    }

    //update change
    if(color == BLACK)
    {
        changeIndexTZS(BLACK, htzs);
    }
    else changeIndexTZS(WHITE, btzs);
    //change finish

    pcore->drawSerie.clear();
}

/** 游戏棋局输入输出相关函数 **/
void BoardScene::output2DBoard(const char* fileName)
{
    FILE *pFile;
    pFile = fopen ( fileName , "wb" );

    //that's the way how to write 2D-array to a bin file
    for(int i=0; i<DIMENSION; i++)
    {
        fwrite (pcore->board[i] , sizeof(int) , sizeof(pcore->board[i])/sizeof(int) , pFile);
    }
    fclose (pFile);
}

void BoardScene::outputSGF(QFile *file, Settings *gameSettings)
{
    IO_sgf *io_sgf = new IO_sgf();

    io_sgf->outputSGF(file, gameSettings, pcore);

    delete io_sgf;
}

void BoardScene::inputSGF(QFile *file, Settings *gameSettings)
{
    io_series coos; //io_series.first           --> 1:BLACK ; -1:WHITE
                    //io_series.second == (0,0) --> PASS Move
    IO_sgf *io_sgf = new IO_sgf();

    bool success = io_sgf->inputSGF(file, gameSettings, &coos); //不正常返回了false

    delete io_sgf;

    if(success)
    {
        //1.) 让子数据设置
        if(gameSettings->get_HA() != 0)
        {
            {
                if(pcore->load_changeHandicaps(gameSettings))
                {
                    changeYesImage(WHITE);
                    pcore->initZeroStep();
                    redraw();
                }
            }
        }

        //2.) 其他游戏设置参数设置

        //3.) 实际棋局的恢复
        if(!inputCore(&coos))
        {
            emit loadFailed(); //棋局读入出错, 因为落子坐标有问题或者是禁着点
            return;
        }

        //emit true signals
        emit loadSucceed();
    }
    else
    {
        //emit false signals
        emit loadFailed();
    }
}

bool BoardScene::inputCore(io_series *inputSeries)
{
    if(!inputSeries->empty())
    {
        vector<io_coordinate>::iterator iter;
        for(iter=inputSeries->begin(); iter!=inputSeries->end(); iter++)
        {
            int cc = iter->first;
            int xx = (iter->second).first;
            int yy = (iter->second).second;

            assert(cc == pcore->whos_turn);

            //先判断是不是pass move
            if(xx==0 && yy==0) pass();

            else
            {
                goCore(xx,yy); //operating Data from CoreCode

                if(!((pcore->drawSerie).empty()))
                {
                    //if we do make a certain move, then we emit some signals to operating GUI
                    if(pcore->block_index == 2)
                    {
                        emit openReview();
                        emit disableGameSettings();
                    }

                    int x,y;
                    int color = (-1)*(pcore->whos_turn); //atm the value of whos_turn doesnt represtent the current status
                                                         //so it has to be multiplied by -1 once more
                    vector<coordinate>::iterator ibegin = (pcore->drawSerie).begin();
                    vector<coordinate>::iterator iend = (pcore->drawSerie).end();

                    //draw the current stone
                    x = ibegin->first;
                    y = ibegin->second;
                    createStone(color,x,y);
                    createIndex(color,x,y,(pcore->block_index)-1);

                    //change items in infoBlock
                    changeIndexLableString(++info_index);
                    changeSquare(x,y);
                    changeYesImage(pcore->whos_turn);
                    //change finish

                    ibegin++;

                    //take off other stones if have to do so
                    for(ibegin; ibegin!=iend; ibegin++) //ibegin statement throw out a warning ignore it, it should be fine
                    {
                        x = ibegin->first;
                        y = ibegin->second;
                        deleteStone(x,y);

                        //change htzs&btzs in infoBlock
                        if( color == BLACK )
                        {
                            htzs++;
                        }
                        else btzs++;
                    }

                    //update change
                    if(color == BLACK)
                    {
                        changeIndexTZS(BLACK, htzs);
                    }
                    else changeIndexTZS(WHITE, btzs);
                    //change finish

                    pcore->drawSerie.erase((pcore->drawSerie).begin(), (pcore->drawSerie).end()); //delete all elements in the drawSerie Vector
                }
                else return false;
            }
        }
        return true;
    }
    else return true;
}

/** 改变游戏设置的相关函数 **/
void BoardScene::changeHandicaps(int i)
{
    /* 内部数据变化调用pcore中的changeHandicaps(int)函数 */
    pcore->changeHandicaps(i);

    /* 界面的变化在这里完成 */
    if(i==1) changeYesImage(BLACK);
    else changeYesImage(WHITE);

    pcore->initZeroStep(); //可有可无, 放在这里使逻辑更清晰一点
    redraw();
}
